package com.niuwa.p2p.service.iml.springsecurity;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.niuwa.p2p.entity.role.Role;
import com.niuwa.p2p.service.resource.ResourcesService;
import com.niuwa.p2p.service.role.RoleService;
import com.niuwa.p2p.service.user.UserService;

/**
 * 
 * 该类的主要作用是为Spring Security提供一个经过用户认证后的UserDetails。
 * 该UserDetails包括用户名、密码、是否可用、是否过期等信息。
 * 
 * @version 1.0
 * @2015年2月6日
 * @author zoudongfang
 *
 */
public class MyUserDetailServiceImpl implements UserDetailsService {

	@Autowired
	private UserService userService;

	@Autowired
	private RoleService roleService;
	
	@Autowired
	private ResourcesService resourcesService;
	
	
	public static Map<String, Collection<ConfigAttribute>> resourceMap = null;;
	

	/**
	 * 
	 * 通过用户名返回UserDetails对象
	 * 
	 * @param username
	 * @return UserDetails
	 * @author zoudongfang
	 * 
	 */
	@Override
	public UserDetails loadUserByUsername(String loginName)
			throws UsernameNotFoundException, DataAccessException {

		Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();

		// 得到用户的权限
		List<Role> roleList = roleService.searchRolesByloginName(loginName);

		String password = new String();

		for (Role role : roleList) {
			GrantedAuthority ga = new GrantedAuthorityImpl(role.getId());
			auths.add(ga);
		}

		// 取得用户的密码
		password = userService.getPasswordByLoginName(loginName);

		if (password == null) {
			throw new UsernameNotFoundException("用户名不正确", loginName);
		}
		
		loadResourceDefine();
		boolean enables = true;
		boolean accountNonExpired = true;
		boolean credentialsNonExpired = true;
		boolean accountNonLocked = true;
		return new User(loginName, password, enables, accountNonExpired,
				credentialsNonExpired, accountNonLocked, auths);
	}
    
	
	/*
	 * 应当是资源为key， 权限为value。 资源通常为url， 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
	 */
	private void loadResourceDefine() {
		List<String> resourceUrlList = resourcesService.searchDistinctResource();
		List<HashMap<String, Object>> resourceList = resourcesService.searchResources();
	       resourceMap	 = new HashMap<String, Collection<ConfigAttribute>>();
		
		/*
		 * for (Role role : roleList) { ConfigAttribute ca = new
		 * SecurityConfig(role.getId()); for (Resource resource : resourceList)
		 * { String url = resource.getUrl(); if (resourceMap.containsKey(url)) {
		 * Collection<ConfigAttribute> value = resourceMap.get(url);
		 * value.add(ca); resourceMap.put(url, value); } else {
		 * Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		 * atts.add(ca); resourceMap.put(url, atts); }
		 * 
		 * }
		 * 
		 * }
		 */
		for (int i = 0; i < resourceUrlList.size(); i++) {
			Collection<ConfigAttribute> roleIdList = new ArrayList<ConfigAttribute>();
			for (int j = 0; j < resourceList.size(); j++) {
				if (resourceUrlList.get(i).equalsIgnoreCase(resourceList.get(j).get("url").toString())) {
					ConfigAttribute ca = new SecurityConfig(resourceList.get(j).get("roleId").toString());
					roleIdList.add(ca);
				}
			}	
			resourceMap.put(resourceUrlList.get(i), roleIdList);	
			}
		
		}
	
	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public RoleService getRoleService() {
		return roleService;
	}

	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}
	public ResourcesService getResourcesService() {
		return resourcesService;
	}

	public void setResourcesService(ResourcesService resourcesService) {
		this.resourcesService = resourcesService;
	}
}
